#include "dvc_status.h"
#include "dvc_cmd_frame.h"
#include "dvc_log.h"
#include "dvc.h"
#include "string.h"

#define DVC_STATUS_DEBUG 1

#if DVC_STATUS_DEBUG
#include "stdio.h"
// #include "elog.h"
#define log_write printf
#else
#define log_write(x)
#endif

static void hex_dump(char *name, uint8_t *data, uint16_t size, uint8_t line_len)
{
    if (!name || !data || !size || !line_len)
        return;
    uint16_t i = 0;
    for (; i < size; i++)
    {
        if (i % line_len == 0)
        {
            log_write("\t");
            if (i)
            {
                for (uint16_t j = 0; j < line_len; j++)
                {
                    if (data[i - line_len + j] < ' ' || data[i - line_len + j] > '~')
                        log_write(".");
                    else
                        log_write("%c", data[i - line_len + j]);
                }
            }
            log_write("\nD/HEX %s: %04X-%04X: ", name, i, i + line_len - 1);
        }
        log_write("%02X ", data[i]);
    }
    if (i % line_len)
    {
        for (uint16_t j = i % line_len; j < line_len; j++)
            log_write("   ");
        log_write("\t");
        for (uint16_t j = 0; j < i % line_len; j++)
        {
            if (data[i - i % line_len + j] < ' ' || data[i - i % line_len + j] > '~')
                log_write(".");
            else
                log_write("%c", data[i - i % line_len + j]);
        }
    }
    log_write("\n");
}

uint8_t dvc_get_status_current_voltage(dvc_t dvc)
{
    if (!dvc)
        return 1;
    if (dvc_frame_read_check(dvc, dvc_cmd_read_status0, (uint8_t *)&dvc->r_status.status0, sizeof(dvc->r_status.status0)))
    {
        log_write("Unable to get status register 0 data\n");
        return 1;
    }

    dvc->r_status.status0.soc_h &= 0x7F;

#ifdef DVC_ENABLE_EVENT_LOG
    dvc_log_event_t event_log = {.timestamp = dvc->tick, .flag = DVC_EVENT_FLAG_AFE, .state = 0, .event = 0};
#define PUSH_LOG_(S_STATE, N_STATE, EVENT, ...)   \
    if (S_STATE != N_STATE)                       \
    {                                             \
        __VA_ARGS__                               \
        {                                         \
            event_log.event = EVENT;              \
            event_log.state = N_STATE;            \
            dvc_log_event_push(dvc, &event_log);  \
            dvc->push = EVENT;                    \
            dvc->push_tick += dvc->push_interval; \
        }                                         \
    }
#define PUSH_LOG(STATE, EVENT, ...) \
    PUSH_LOG_(dvc->status.status0.STATE, dvc->r_status.status0.STATE, EVENT, ##__VA_ARGS__)
#endif

    /* 有 警报 / 异常 */
    if (((uint16_t *)&dvc->r_status.status0)[0] & 0x3FC)
    {
        dvc->alert = 1;
#ifdef DVC_ENABLE_EVENT_LOG
        PUSH_LOG(ocd, DVC_EVENT_TYPE_OCD, {
            if (dvc->r_status.status0.ocd)
            {
                if (!dvc->user_cfg.afe.cccd)
                    dvc->ccd_tick = -1;
                else
                    dvc->ccd_tick = dvc->tick + dvc->user_cfg.afe.cccd * 1000;
            }
        })
        PUSH_LOG(occ, DVC_EVENT_TYPE_OCC, {
            if (dvc->r_status.status0.occ)
            {
                if (!dvc->user_cfg.afe.cccd)
                    dvc->ccd_tick = -1;
                else
                    dvc->ccd_tick = dvc->tick + dvc->user_cfg.afe.cccd * 1000;
            }
        })
        PUSH_LOG(scd, DVC_EVENT_TYPE_SCD, {
            if (dvc->r_status.status0.scd)
            {
                if (!dvc->user_cfg.afe.cscd)
                    dvc->scd_tick = -1;
                else
                    dvc->scd_tick = dvc->tick + dvc->user_cfg.afe.cscd * 1000;
            }
        })
        PUSH_LOG(uv, DVC_EVENT_TYPE_UV, {
            if (dvc->r_status.status0.uv)
            {
                if (!dvc->user_cfg.afe.cccd)
                    dvc->ccd_tick = -1;
                else
                    dvc->uv_tick = dvc->tick + dvc->user_cfg.afe.cccd * 1000;
            }
        })
        PUSH_LOG(ov, DVC_EVENT_TYPE_OV, {
            if (dvc->r_status.status0.ov)
            {
                if (!dvc->user_cfg.afe.cccd)
                    dvc->ccd_tick = -1;
                else
                    dvc->ov_tick = dvc->tick + dvc->user_cfg.afe.cccd * 1000;
            }
        })
        PUSH_LOG(alt_pd, DVC_EVENT_TYPE_ALTER)
        PUSH_LOG(cs_st, DVC_EVENT_TYPE_CSST)
        PUSH_LOG(vs_st, DVC_EVENT_TYPE_VSST)
#endif
    }

#ifdef DVC_ENABLE_EVENT_LOG
    PUSH_LOG(ld, DVC_EVENT_TYPE_LOAD)
    PUSH_LOG(chg_st, DVC_EVENT_TYPE_CHG)
    PUSH_LOG(dsg_st, DVC_EVENT_TYPE_DSG)
#endif

    memcpy(&dvc->status.status0, &dvc->r_status.status0, sizeof(dvc->status.status0));

    /* 计算总线电压和电流 */
    float voltage = ((uint16_t)((dvc->status.status0.soc_h & 0x7F) << 8 | dvc->status.status0.soc_l)) * 1.465 /* 1.465mV */ / 1000 /* mV -> V */ * dvc->calib.voltage;
    float current = -((int16_t)(dvc->status.status0.csv_h << 8 | dvc->status.status0.csv_l)) * 9.155 /* 9.155uV */ / dvc->current_R * dvc->calib.current;

    /* 过滤 < calib.filter_current mA */
    if (abs(current * 1000) < dvc->calib.filter_current)
        current = 0.0f;

    /* 减去 自耗电 电流 */
    float consumable_current = dvc->calib.consumable / voltage;
    if (dvc->low_power) /* 低功耗的情况下, 为默认功耗的 20%, 后期可配置 */
        consumable_current *= 0.2;
    current -= consumable_current;

    float diff = abs((voltage - dvc->bat_totle_voltage) * 100) / 100.0f;
    if (diff < 0.5f)
    {
        if (voltage > dvc->bat_totle_voltage)
            voltage -= diff / 2;
        else
            voltage += diff / 2;
    }

    if (dvc->voltage != voltage)
    {
        /* mV */
        dvc->voltage = voltage;
        dvc->change |= dvc_data_current_change;
    }

    if (dvc->current != current)
    {
        /* uV */
        dvc->current = current;
        dvc->change |= dvc_data_current_change;
    }

    if (dvc->change & dvc_data_current_change)
    {
        /* 计算功率 */
        dvc->power = dvc->voltage * dvc->current;
    }
    return 0;
}

uint8_t dvc_get_bat_voltage(dvc_t dvc)
{
    if (!dvc)
        return 1;
    if (dvc_frame_read_check(dvc, dvc_cmd_read_status1, (uint8_t *)&dvc->r_status.status1, sizeof(dvc->r_status.status1)))
    {
        log_write("Unable to get status register 1 data\n");
        return 1;
    }
    if (dvc_frame_read_check(dvc, dvc_cmd_read_status2, (uint8_t *)&dvc->r_status.status2, sizeof(dvc->r_status.status2)))
    {
        log_write("Unable to get status register 2 data\n");
        return 1;
    }

    dvc->r_status.status1.c1v_h &= 0x7F;
    dvc->r_status.status1.c2v_h &= 0x7F;
    dvc->r_status.status1.c3v_h &= 0x7F;
    dvc->r_status.status2.c4v_h &= 0x7F;
    dvc->r_status.status2.c5v_h &= 0x7F;
    dvc->r_status.status2.c6v_h &= 0x7F;

    uint32_t bat_vol[6] = {0};
    bat_vol[0] = dvc->r_status.status1.c1v_h << 8 | dvc->r_status.status1.c1v_l;
    bat_vol[1] = dvc->r_status.status1.c2v_h << 8 | dvc->r_status.status1.c2v_l;
    bat_vol[2] = dvc->r_status.status1.c3v_h << 8 | dvc->r_status.status1.c3v_l;
    bat_vol[3] = dvc->r_status.status2.c4v_h << 8 | dvc->r_status.status2.c4v_l;
    bat_vol[4] = dvc->r_status.status2.c5v_h << 8 | dvc->r_status.status2.c5v_l;
    bat_vol[5] = dvc->r_status.status2.c6v_h << 8 | dvc->r_status.status2.c6v_l;

    float voltage = 0;
    for (uint8_t i = 0; i < dvc->bat_num; i++)
    {
        bat_vol[i] = bat_vol[i] * 1831 / 1000 / 10;
        voltage += bat_vol[i];
    }
    dvc->bat_totle_voltage = voltage;
    memcpy(&dvc->status.status1, &dvc->r_status.status1, sizeof(dvc->status.status1));
    memcpy(&dvc->status.status2, &dvc->r_status.status2, sizeof(dvc->status.status2));

    uint16_t diff_max = 0; // 差值最大值
    for (uint8_t i = 0; i < dvc->bat_num; i++)
    {
        if (dvc->bat_vol[i] != bat_vol[i])
        {
            dvc->bat_vol[i] = bat_vol[i];
            dvc->change |= dvc_data_voltage_change;
        }
        for (uint8_t j = i + 1; j < dvc->bat_num; j++)
        {
            uint16_t diff = abs(bat_vol[i] - bat_vol[j]);
            if (diff > diff_max)
                diff_max = diff;
        }
    }

    /* 均衡逻辑 */
    static const uint32_t aes_no_check_time = 1 * 60 * 60 * 1000; // 1小时
    if (dvc->aes_user)                                            /* 用户指定开启状态 */
    {
        if (dvc->aes != 1)
            dvc_aes(dvc, 1, DVC_EVENT_FLAG_AFE);
    }
    /* 用户关闭 / 没有操作过 */
    else if (!dvc->aes_tick /* 用户没有操作过 - 自动均衡 */ || dvc->tick - dvc->aes_tick >= aes_no_check_time /* 过去指定时间 内没有用户操作过 - 自动进入 自动均衡 模式 */)
    {
        if (!dvc->aes) /* 如果均衡未开启 */
        {
            /* 达到开启均衡条件 */
            if (diff_max >= dvc->user_cfg.aes.max * 1000)
                dvc_aes(dvc, 1, DVC_EVENT_FLAG_AFE);
        }
        else
        {
            /* 达到关闭均衡条件 */
            if (diff_max < dvc->user_cfg.aes.min * 1000)
                dvc_aes(dvc, 0, DVC_EVENT_FLAG_AFE);
        }
    }
    dvc->bat_diff = diff_max;
    return 0;
}

uint8_t dvc_get_temp(dvc_t dvc)
{
    if (!dvc)
        return 1;
    if (dvc_frame_read_check(dvc, dvc_cmd_read_status3, (uint8_t *)&dvc->r_status.status3, sizeof(dvc->r_status.status3)))
    {
        log_write("Unable to get status register 3 data\n");
        return 1;
    }
    memcpy(&dvc->status.status3, &dvc->r_status.status3, sizeof(dvc->status.status3));

    // 取 15 位有效值
    uint16_t tsv_raw = ((dvc->status.status3.tsv_h & 0x7F) << 8) | dvc->status.status3.tsv_l;
    uint16_t tcv_raw = ((dvc->status.status3.tcv_h & 0x7F) << 8) | dvc->status.status3.tcv_l;

    // 转换为 mV
    float temp_vol = tsv_raw * 0.1831f; // 183.1 μV → mV
    // 芯片温度换算（假设 -249*V + 571）
    float mcu_temp = -249.0f * (tcv_raw * 183.1e-6f) + 571.0f;

    if (dvc->temp_vol != (uint32_t)temp_vol)
    {
        dvc->temp_vol = (uint32_t)temp_vol;
        if (dvc->ops && dvc->ops->get_temp)
            dvc->temp = dvc->ops->get_temp(dvc->temp_vol);
        dvc->change |= dvc_data_temp_change;
    }

    if (dvc->mcu_temp != mcu_temp)
    {
        dvc->mcu_temp = mcu_temp;
        dvc->change |= dvc_data_temp_change;
    }
    return 0;
}

uint16_t dvc_get_result_to(dvc_t dvc, uint8_t *data, uint16_t len)
{
    if (!dvc || !data || !len)
        return 0;
    char *p = (char *)data;
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "{\"voltage\":%f,", dvc->voltage);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"current\": %f,", dvc->current);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"power\": %f,", dvc->power);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"mAh\":%f,", dvc->coulomb_counter.sum.mA / 3.6f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"mWh\":%f,", dvc->coulomb_counter.sum.mW / 3.6f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"mAh_chg\":%f,", dvc->coulomb_counter.chg.mA / 3.6f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"mWh_chg\":%f,", dvc->coulomb_counter.chg.mW / 3.6f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"mAh_dsg\":%f,", dvc->coulomb_counter.dsg.mA / 3.6f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"mWh_dsg\":%f,", dvc->coulomb_counter.dsg.mW / 3.6f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"bat_ah\":%f,", dvc->coulomb_counter.bat_mA / 3.6f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"bat_rah\":%f,", dvc->coulomb_counter.bat_rmA / 3.6f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"bat_soh\":%.3f,", dvc->coulomb_counter.bat_health * 100);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"alert\":%u,", dvc->alert);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"time\":%lu,", dvc->tick);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"rtime\":%lu,", dvc->coulomb_counter.bat_rtime);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"bat_diff\":%u,", dvc->bat_diff);
    if (dvc->bat_num)
    {
        p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"bat\":[");
        for (uint8_t i = 0; i < 6; i++)
        {
            if (i >= dvc->bat_num)
                break;
            p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "%d.%03d,", dvc->bat_vol[i] / 1000, dvc->bat_vol[i] % 1000);
        }
        p--;
        p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "],");
    }
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"state\":{");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"CHG\":%d,", dvc->status.status0.chg_st);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"DSG\":%d,", dvc->status.status0.dsg_st);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"OCD\":%d,", dvc->status.status0.ocd);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"SCD\":%d,", dvc->status.status0.scd);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"UV\":%d,", dvc->status.status0.uv);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"OV\":%d,", dvc->status.status0.ov);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"OCC\":%d,", dvc->status.status0.occ);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"Alert\":%d,", dvc->status.status0.alt_pd);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"CS\":%d,", dvc->status.status0.cs_st);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"VS\":%d,", dvc->status.status0.vs_st);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"Load\":%d,", dvc->status.status0.ld);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"AE\":%d", dvc->aes);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "},");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"mcu_temp\": %f,", dvc->mcu_temp);
    if (dvc->ops->get_temp)
        p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"temp\":%f,", dvc->temp);
    else
        p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"temp\":%ldmV,", dvc->temp_vol);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"raw\":{");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"voltage\":%f,", ((uint16_t)(dvc->status.status0.soc_h << 8 | dvc->status.status0.soc_l)) * 1.465);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"current\":%f,", ((int16_t)(dvc->status.status0.csv_h << 8 | dvc->status.status0.csv_l)) * 9.155);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"temp\":%f,", (dvc->status.status3.tsv_h << 8 | dvc->status.status3.tsv_l) * 183.1);
    p--;
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "},");
    p--;
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "}");
    return p - (char *)data;
}

uint16_t dvc_get_result_to_bemfa(dvc_t dvc, uint8_t *data, uint16_t len)
{
    if (!dvc || !data || !len)
        return 0;
    char *p = (char *)data;
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%.3f", dvc->voltage);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%.3f", dvc->current);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%.3f", dvc->power);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%.3f", dvc->coulomb_counter.sum.mA / 3600.0f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%.3f", dvc->coulomb_counter.sum.mW / 3600.0f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%.3f", dvc->coulomb_counter.chg.mA / 3600.0f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%.3f", dvc->coulomb_counter.chg.mW / 3600.0f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%.3f", dvc->coulomb_counter.dsg.mA / 3600.0f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%.3f", dvc->coulomb_counter.dsg.mW / 3600.0f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%.1f", dvc->coulomb_counter.bat_rmA / 3600.0f);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%d", dvc->alert);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%ld", dvc->tick / 1000);
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%ld", dvc->coulomb_counter.bat_rtime / 1000 / 60); /* 分钟 */
    if (dvc->bat_num)
    {
        for (uint8_t i = 0; i < 6; i++)
        {
            if (i >= dvc->bat_num)
                break;
            p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%d.%03d", dvc->bat_vol[i] / 1000, dvc->bat_vol[i] % 1000);
        }
    }
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%.3f", dvc->mcu_temp);
    if (dvc->ops->get_temp)
        p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%.3f#", dvc->temp);
    else
        p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "#%ld#", dvc->temp_vol);
    return p - (char *)data;
}

void dvc_get_state_to(dvc_t dvc, uint8_t *data, uint16_t len)
{
    if (!dvc || !data || !len)
        return;
    char *p = (char *)data;
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "{\"CHG\":\"%s\",", dvc->status.status0.chg_st ? "Enable" : "Disable");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"DSG\":\"%s\",", dvc->status.status0.dsg_st ? "Enable" : "Disable");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"OCD\":\"%s\",", dvc->status.status0.ocd ? "OverCurrent" : "Normal");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"SCD\":\"%s\",", dvc->status.status0.scd ? "ShortCircuit" : "Normal");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"UV\":\"%s\",", dvc->status.status0.uv ? "UnderVoltage" : "Normal");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"OV\":\"%s\",", dvc->status.status0.ov ? "OverVoltage" : "Normal");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"OCC\":\"%s\",", dvc->status.status0.occ ? "OverCurrent" : "Normal");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"Alert\":\"%s\",", dvc->status.status0.alt_pd ? "Yes" : "Normal");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"CSST\":\"%s\",", dvc->status.status0.cs_st ? "Failure" : "Normal");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"VSST\":\"%s\",", dvc->status.status0.vs_st ? "Failure" : "Normal");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"AE\":\"%s\",", dvc->aes ? "Enable" : "Disable");
    p += snprintf(p, len - ((uintptr_t)p - (uintptr_t)data), "\"Load\":\"%s\"}", dvc->status.status0.ld ? "Normal" : "Null");
}

uint8_t dvc_clear_alert(dvc_t dvc, uint8_t flag)
{
    if (!dvc)
        return 1;
    uint8_t data = 0xFF;
    if (dvc_frame_write(dvc, dvc_cmd_clear_cmd, &data, 1))
    {
        log_write("Unable to clear alarm\n");
        return 1;
    }
    dvc->ov_tick = dvc->uv_tick = dvc->scd_tick = dvc->aes_tick = 0;

#ifdef DVC_ENABLE_EVENT_LOG
    dvc_log_event_t event_log = {
        .timestamp = dvc->tick,
        .event = DVC_EVENT_TYPE_CLEAR_ALTER,
        .flag = flag ? DVC_EVENT_FLAG_USER : DVC_EVENT_FLAG_AFE,
        .state = 0,
    };
    dvc_log_event_push(dvc, &event_log);
#endif
    return 0;
}
